package org.hcyspartnoc.luoxin.common.core.config;

import com.alibaba.fastjson2.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.toolkit.Db;
import org.hcyspartnoc.luoxin.common.core.AjaxResult;
import org.hcyspartnoc.luoxin.common.core.configuration.ContrapsychConfiguration;
import org.hcyspartnoc.luoxin.common.core.configuration.ServiceConfiguration;
import org.hcyspartnoc.luoxin.common.enums.chat.ChatMessageTypeEnum;
import org.hcyspartnoc.luoxin.common.enums.service.ServiceCounselorStatusEnum;
import org.hcyspartnoc.luoxin.mapper.asset.AssetVirtualCounselorMapper;
import org.hcyspartnoc.luoxin.mapper.chat.ChatCounselingSessionMapper;
import org.hcyspartnoc.luoxin.mapper.chat.ChatSessionMapper;
import org.hcyspartnoc.luoxin.mapper.service.ServiceCounselorOrderMapper;
import org.hcyspartnoc.luoxin.mapper.service.ServicePaymentMapper;
import org.hcyspartnoc.luoxin.pojo.po.asset.AssetVirtualCounselorPo;
import org.hcyspartnoc.luoxin.pojo.po.chat.ChatCounselingSessionPo;
import org.hcyspartnoc.luoxin.pojo.po.chat.ChatSessionNotePo;
import org.hcyspartnoc.luoxin.pojo.po.chat.ChatSessionPo;
import org.hcyspartnoc.luoxin.pojo.po.service.ServiceCounselorOrderPo;
import org.hcyspartnoc.luoxin.pojo.po.service.ServicePaymentPo;
import org.hcyspartnoc.luoxin.pojo.vo.chat.ChatCommonVo;
import org.hcyspartnoc.luoxin.service.chat.impl.ChatSessionNoteServiceImpl;
import org.hcyspartnoc.luoxin.utils.*;
import org.hcyspartnoc.luoxin.utils.redis.RedisComponent;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.time.Duration;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.List;
import java.util.Objects;

//@Component
public class ScheduledTasks {
    private static final Logger logger = LoggerFactory.getLogger(ScheduledTasks.class);
    @Resource
    private ChatSessionMapper chatSessionMapper;
    @Resource
    private ContrapsychConfiguration contrapsychConfiguration;
    @Resource
    private RedisComponent redisComponent;
    @Resource
    private ServicePaymentMapper servicePaymentMapper;
    @Resource
    private ServiceConfiguration serviceConfiguration;
    @Resource
    private AssetVirtualCounselorMapper assetVirtualCounselorMapper;
    @Resource
    private ServiceCounselorOrderMapper serviceCounselorOrderMapper;
    @Resource
    private WeiXinUtils weiXinUtils;
    @Resource
    private ChatCounselingSessionMapper chatCounselingSessionMapper;
    @Resource
    private ChannelContextUtils channelContextUtils;

    @Scheduled(cron = "0 0 4 * * ?")
    @Transactional
    public void handleServerTime() {
        // 将用户的每日可聊天次数重置为10（除了-1用户）
        int update = chatSessionMapper.update(new LambdaUpdateWrapper<>(ChatSessionPo.class)
                .gt(ChatSessionPo::getFreeChatTimes, -1)
                .set(ChatSessionPo::getFreeChatTimes, contrapsychConfiguration.getChat().getDailyFree()));
        // 清除记忆体
        redisComponent.removeChatVcMemory();
        logger.info("服务器时间4点:清除了咨询师记忆体，更新了用户免费聊天次数，总计跟新会话数量：{}", update);
    }

    @Scheduled(fixedRate = 5000)
    @Transactional
    public void cancelOverdueOrder() {
        // 查找 当前时间 - 创建时间 > 设定过期时间
        LambdaQueryWrapper<ServiceCounselorOrderPo> wrapper = new LambdaQueryWrapper<>(ServiceCounselorOrderPo.class)
                .eq(ServiceCounselorOrderPo::getStatus, ServiceCounselorStatusEnum.NO_PAY.getCode())
                .lt(ServiceCounselorOrderPo::getCreatedAt, LocalDateTime.now().minus(Duration.ofSeconds(serviceConfiguration.getOrder().getExpires())));
        List<ServiceCounselorOrderPo> serviceCounselorOrderPos = serviceCounselorOrderMapper.selectList(wrapper);
        List<Long> idList = serviceCounselorOrderPos.stream().map(ServiceCounselorOrderPo::getId).toList();
        if (!idList.isEmpty()) {
            // 关闭微信订单
            List<ServicePaymentPo> servicePaymentPos = servicePaymentMapper.selectList(new LambdaQueryWrapper<>(ServicePaymentPo.class)
                    .in(ServicePaymentPo::getOrderId, idList));
            for (ServicePaymentPo servicePaymentPo : servicePaymentPos) {
                // 如果微信订单关闭成功，将本地对应订单状态设为取消顶顶那
                if (weiXinUtils.closeOrder(servicePaymentPo)) {
                    // 修改订单状态
                    serviceCounselorOrderMapper.update(new LambdaUpdateWrapper<>(ServiceCounselorOrderPo.class)
                            .eq(ServiceCounselorOrderPo::getId, servicePaymentPo.getOrderId())
                            .set(ServiceCounselorOrderPo::getStatus, ServiceCounselorStatusEnum.CANCELLED.getCode()));
                }
            }
        }
    }

    @Scheduled(fixedRate = 5000)
    @Transactional
    public void closeInProgressOrder() {
        // 开启时间小于当前时间-预约时间
        LambdaQueryWrapper<ServiceCounselorOrderPo> wrapper = new LambdaQueryWrapper<ServiceCounselorOrderPo>()
                .eq(ServiceCounselorOrderPo::getStatus, ServiceCounselorStatusEnum.IN_PROGRESS.getCode())
                .ltSql(ServiceCounselorOrderPo::getStartTime, "NOW() - INTERVAL service_duration MINUTE");
        List<ServiceCounselorOrderPo> serviceCounselorOrderPos = serviceCounselorOrderMapper.selectList(wrapper);
        if (!serviceCounselorOrderPos.isEmpty()) {
            List<Long> orderIds = serviceCounselorOrderPos.stream().map(ServiceCounselorOrderPo::getId).toList();
            List<Integer> sessionIds = serviceCounselorOrderPos.stream().map(ServiceCounselorOrderPo::getSessionId).toList();
            // 结束订单
            serviceCounselorOrderMapper.update(new LambdaUpdateWrapper<>(ServiceCounselorOrderPo.class)
                    .in(ServiceCounselorOrderPo::getId, orderIds)
                    .set(ServiceCounselorOrderPo::getStatus, ServiceCounselorStatusEnum.COMPLETED.getCode())
                    .set(ServiceCounselorOrderPo::getEndTime, LocalDateTime.now()));
            // 结束订单对应的会话
            chatCounselingSessionMapper.update(new LambdaUpdateWrapper<>(ChatCounselingSessionPo.class)
                    .in(ChatCounselingSessionPo::getId, sessionIds)
                    .set(ChatCounselingSessionPo::getStatus, false));
        }
        // 发送消息给前端->该咨询会话已结束
        for (ServiceCounselorOrderPo orderPo : serviceCounselorOrderPos) {
            // 生成咨询手记
            HashMap<String, Object> result = new HashMap<>();
            result.put("isGenerateNote", false);
            MultimediaUtils.ChatReqBody chatReqBody = JSON.parseObject(redisComponent.getChatOrderVCMemory(orderPo.getSessionId().toString()), MultimediaUtils.ChatReqBody.class);
            int rounds = 0;
            if (Objects.nonNull(chatReqBody)) {
                rounds = chatReqBody.getMessages().stream()
                        .filter(msg -> msg.getRole().equals(LuoxinUtils.LUOXIN_AI_ROLE)).toList().size();
            }
            if (rounds > 10) {
                String note = "";
                Integer maxRetries = contrapsychConfiguration.getNote().getMaxRetries();
                while (maxRetries-- > 0 && note.isEmpty()) {
                    note = MultimediaUtils.generateNote(chatReqBody);
                }
                if (!note.isEmpty()) {
                    ChatSessionNotePo chatSessionNotePo = new ChatSessionNotePo();
                    chatSessionNotePo.setCounselingSessionId(orderPo.getSessionId())
                            .setUserId(orderPo.getUserId())
                            .setContent(note)
                            .setScOrderId(orderPo.getId())
                            .setNoteTitle("情感问题")
                            .setCounselingDuration(orderPo.getServiceDuration())
                            .setCounselingRounds(rounds);
                    if (orderPo.getCounselorId().charAt(0) == 'V') {
                        AssetVirtualCounselorPo assetVirtualCounselorPo = assetVirtualCounselorMapper.selectById(Integer.parseInt(orderPo.getCounselorId().substring(1)));
                        if (Objects.nonNull(assetVirtualCounselorPo))
                            chatSessionNotePo.setCounselorName(assetVirtualCounselorPo.getName());
                    }
                    Db.save(chatSessionNotePo);
                    result.put("isGenerateNote", true);
                    result.put("note", ChatSessionNoteServiceImpl.notePoToVo(chatSessionNotePo));
                }
            }
            // 删除记忆体
            redisComponent.removeChatOrderVcMemory(orderPo.getSessionId().toString());
            // 发送订单结束消息给前端
            String masterSessionId = chatCounselingSessionMapper.selectById(orderPo.getSessionId()).getMasterSessionId();
            ChatCommonVo chatCommonVo = new ChatCommonVo();
            chatCommonVo.setMessageContent(result)
                    .setMessageType(ChatMessageTypeEnum.ORDER_SESSION_END)
                    .setSessionId(masterSessionId);
            channelContextUtils.sendToUser(orderPo.getUserId().toString(), JSON.toJSONString(AjaxResult.success(chatCommonVo)));
        }
        logger.info("订单轮询结束了{}条订单", serviceCounselorOrderPos.size());
    }


    @Scheduled(fixedRate = 5 * 60 * 1000)
    public void clearTempDir() {
        BaiFileUtils.deleteFilesOlderThan(contrapsychConfiguration.getTempFilesDir(), Duration.ofSeconds(600));
    }
}




